#include "dominion.h"
#include "dominion_helpers.h"
#include "rngs.h"
#include "testutils.h"
#include "interface.h"
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <stdbool.h>
#include <sys/time.h>
#include <time.h>
#include <assert.h>
#include <getopt.h>
#include <string.h>
#include <stdarg.h>

// This is an integration test designed to test playing multiple action cards
// in the same turn and getting multiple coin bonuses that add up. Code 
// inspection gave me reason to believe that this wouldn't work properly. The
// individual cards being played aren't tested that thoroughly, that's the job
// of the unit tests.

// Test the action card combo of village, minion, minion
void testVillageMinionMinionEffect (int village_pos, int minion1_pos, int minion2_pos)
{
    needed_card_t nc[3];
    struct gameState G;
    expectedState_t expected;
    
    // Arrange them so that they can be played one after the other from the
    // end. (NOTE: if the algorithm to remove a card from the player's hand is
    // not specified and is implementation-specific, then this code won't be
    // good enough.)
    nc[0].cardtype = village;
    nc[0].position = village_pos;
    nc[1].cardtype = minion;
    nc[1].position = minion1_pos;
    nc[2].cardtype = minion;
    nc[2].position = minion2_pos;
    
    setup_test_game (3, nc, &G, &expected);
    
    pass_printf (   "%s: TEST playing a Village at position %d, "
                    "Minion at position %d, Minion at position %d\n",
                    __func__, village_pos, minion1_pos, minion2_pos );
    
    // Test playing the village
    // Since the village draws a card before discarding itself, it does not 
    // cause the two minion cards to have different positions in the hand.
    testPlayCard (village_pos, 0, 0, 0, &G, &expected, false);
    
    // Test playing the first minion. This can cause the second minion to move
    // around within the player's hand under certain circumstances.
    if (minion2_pos == 7)
        minion2_pos = minion1_pos;
    int expectedCoins = G.coins + 2;
    
    testPlayCard (minion1_pos, 1, 0, 0, &G, &expected, false);
    
    assert_equal (G.coins, expectedCoins, "verifying the number of coins");
    
    // Test playing the second minion
    expectedCoins = G.coins + 2;
    
    testPlayCard (minion2_pos, 1, 0, 0, &G, &expected, false);
    
    assert_equal (G.coins, expectedCoins, "verifying the number of coins");
    
    // Misc. sanity checking
    testEndTurn (&G, &expected);
    
    log_flush ();
}

int main (int argc, char *argv[])
{
    parse_args (argc, argv);
    
    for (int village_pos = 0; village_pos < 8; village_pos++)
    {
        for (int minion1_pos = 0; minion1_pos < 8; minion1_pos++)
        {
            if (village_pos == minion1_pos)
                continue;
            for (int minion2_pos = 0; minion2_pos < 8; minion2_pos++)
            {
                if (village_pos == minion2_pos || minion1_pos == minion2_pos)
                    continue;
                testVillageMinionMinionEffect (village_pos, minion1_pos, minion2_pos);
            }
        }
    }
}
